package com.vita.core;

import java.util.LinkedList;
import java.util.Objects;
import java.util.Queue;

import com.vita.core.function.Func;
import com.vita.core.function.FuncActuator;

/**
 * 每个Ico里面都有一个value，用来储存Ico执行前的入参
 */
public class Ico extends ValueStore<Object> {
    /**
     * 当input、convert、output在构建时需要额外的参数，可以向“bank”借参
     */
    private Queue<Object> bank = new LinkedList<Object>();
    private Func inputAct = (o)->o;
    private Func convertAct;
    private Func outputAct = (o)->o;
    

    /**
     * 输入执行器:将需要转换的内容构建为java对象
     */
    public <I> Ico input(I i){
        return Helper.input(i);
    }
    public Ico input(Func input){
        this.inputAct = input;
        return this;
    }

     /**
      * 直接输入java对象，不需要输入执行器时调用
      * @return 返回参数为Ico对象（转换器、输出执行器缺省）
      */
    public Ico input(){
        return this;
    }

     /**
      * 获取转换器
      * @param convert 转换器（将一个java对象转换为另一个java对象）
      * @return 返回参数为Ico对象（输出执行器缺省）
      */
    public Ico convert(Func convert){
        this.convertAct = convert;
        return this;
    }

     /**
      * 获取输出执行器
      * @return 返回参数为完整的Ico对象
      */
    public <O> Ico output(O o){
        this.outputAct = Helper.output(o);
        return this;
    }

    public <O> Ico output(Func o){
        this.outputAct = o;
        return this;
    }

    /**
     * 直接输出java对象，不需要输出执行器时调用
     */
    public Ico output(){
        return this;
    }


    /**
     * 获取Input输入对象
     */
    public Func getInputAct(){
        return this.inputAct;
    }

    /**
     * 获取Output输出对象
     */
    public Func getOutputAct(){
        return this.outputAct;
    }

    /**
     * 获取Convert转换对象
     */
    public Func getConvertAct(){
        return this.convertAct;
    }

    /**
     * 获取runInput后的值
     */
    public Object getInputValue() {
        return FuncActuator.run(this.inputAct, getValue(),this.bank);
    }

    /**
     * 获取runConvert后的值
     */
    public Object getConvertValue() {
        Objects.requireNonNull(this.convertAct,"转换器缺省");
        return FuncActuator.run(this.convertAct, getInputValue(),this.bank);
    }

    /**
     * 获取runOutput后的值
     * 转换完成必须清空value
     */
    private Object getOutputValue() {
        Object object = FuncActuator.run(this.outputAct, getConvertValue(),this.bank);
        clear();
        return object;
    }

    public Ico saveParam(Object param){
        this.bank.add(param);
        return this;
    }

    /**
     * 清空入值，以便再次使用
     */
    private void clear() {
        this.setValue(null);
    }

    /**
     * 执行run(),直接得到转换对象
     */
    public Object run() {
        return getOutputValue();
    }

    public <I> Object run(I i) {
        this.setValue(i);
        return run();
    }

    public <I,O> O run(I i,O o) {
        return (O)run(i);
    }

    public <I,O,E> O run(I i,O o,E extra){
        this.bank.add(extra);
        return (O)run(i,o);
    }

}
